from django.shortcuts import render, get_object_or_404
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required, permission_required
from django.http import HttpResponseRedirect, JsonResponse
from django.urls import reverse, reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db.models import Count, Avg, Q
from django.utils import timezone
import datetime
from django.views.decorators.http import require_POST
from django.views import View
from .ai_utils import deepseek_chat
from django.views.decorators.csrf import csrf_exempt

from .models import Book, Author, BookInstance, Genre, Language, Review, BookLike, BookFavorite
from .forms import RenewBookForm, ReviewForm

def index(request):
    """View function for home page of site."""
    # Generate counts of some of the main objects
    num_books = Book.objects.all().count()
    num_instances = BookInstance.objects.all().count()
    
    # Available books (status = 'a')
    num_instances_available = BookInstance.objects.filter(status__exact='a').count()
    
    # The 'all()' is implied by default.    
    num_authors = Author.objects.filter(book__isnull=False).distinct().count()
    
    # Get popular books based on number of borrows
    popular_books = Book.objects.annotate(
        borrow_count=Count('bookinstance')
    ).order_by('-borrow_count')[:5]
    
    # Get recent reviews
    recent_reviews = Review.objects.select_related('book', 'user').order_by('-created_at')[:3]
    
    # Get AI recommendations for logged-in users
    ai_recommendations = None
    if request.user.is_authenticated:
        # Get user's borrowed books
        user_borrowed = BookInstance.objects.filter(
            borrower=request.user,
            status__exact='o'
        ).values_list('book', flat=True)
        
        # Get books in the same genres as borrowed books
        if user_borrowed:
            borrowed_books = Book.objects.filter(id__in=user_borrowed)
            genres = Genre.objects.filter(book__in=borrowed_books).distinct()
            ai_recommendations = Book.objects.filter(
                genre__in=genres
            ).exclude(
                id__in=user_borrowed
            ).distinct()[:3]
    
    context = {
        'num_books': num_books,
        'num_instances': num_instances,
        'num_instances_available': num_instances_available,
        'num_authors': num_authors,
        'popular_books': popular_books,
        'recent_reviews': recent_reviews,
        'ai_recommendations': ai_recommendations,
    }

    return render(request, 'index.html', context=context)

from django.db.models import Q

class BookListView(generic.ListView):
    model = Book
    paginate_by = 10

    def get_queryset(self):
        queryset = super().get_queryset().annotate(
            avg_rating=Avg('reviews__rating')
        )
        q = self.request.GET.get('q')
        if q:
            queryset = queryset.filter(
                Q(title__icontains=q) | Q(author__name__icontains=q)
            )
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'All Books'
        context['q'] = self.request.GET.get('q', '')
        return context

class BookDetailView(generic.DetailView):
    model = Book
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        book = self.get_object()
        context['header'] = book.title
        context['reviews'] = book.reviews.all().order_by('-created_at')
        context['review_form'] = ReviewForm()
        context['like_count'] = book.booklike_set.count()
        context['liked'] = False
        if self.request.user.is_authenticated:
            context['liked'] = book.booklike_set.filter(user=self.request.user).exists()
        context['fav_count'] = book.bookfavorite_set.count()
        context['favorited'] = False
        if self.request.user.is_authenticated:
            context['favorited'] = book.bookfavorite_set.filter(user=self.request.user).exists()
        return context

class AuthorListView(generic.ListView):
    model = Author
    paginate_by = 10
    queryset = Author.objects.filter(book__isnull=False).distinct()
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'All Authors'
        return context

class AuthorDetailView(generic.DetailView):
    model = Author

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        author = self.get_object()
        context['header'] = author.name
        return context

class LoanedBooksByUserListView(LoginRequiredMixin, generic.ListView):
    """Generic class-based view listing books on loan to current user."""
    model = BookInstance
    template_name = 'catalog/bookinstance_list_borrowed_user.html'
    paginate_by = 10
    
    def get_queryset(self):
        return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'My Borrowed Books'
        return context

class AllBorrowedBooksListView(PermissionRequiredMixin, generic.ListView):
    """Generic class-based view listing all books on loan."""
    model = BookInstance
    template_name = 'catalog/bookinstance_list_all_borrowed.html'
    paginate_by = 10
    permission_required = 'catalog.can_mark_returned'
    
    def get_queryset(self):
        return BookInstance.objects.filter(status__exact='o').order_by('due_back')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'All Borrowed Books'
        return context

@login_required
def renew_book_librarian(request, pk):
    """View function for renewing a specific BookInstance by librarian."""
    book_instance = get_object_or_404(BookInstance, pk=pk)

    # If this is a POST request then process the Form data
    if request.method == 'POST':
        # Create a form instance and populate it with data from the request
        form = RenewBookForm(request.POST)

        # Check if the form is valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            book_instance.due_back = form.cleaned_data['renewal_date']
            book_instance.save()

            # redirect to a new URL:
            return HttpResponseRedirect(reverse('all-borrowed'))

    # If this is a GET (or any other method) create the default form
    else:
        proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
        form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})

    context = {
        'form': form,
        'book_instance': book_instance,
        'header': 'Renew Book',
    }

    return render(request, 'catalog/book_renew_librarian.html', context)

@login_required
def add_review(request, pk):
    """View function for adding a review to a book."""
    book = get_object_or_404(Book, pk=pk)
    
    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid():
            review = form.save(commit=False)
            review.book = book
            review.user = request.user
            review.save()
            return HttpResponseRedirect(reverse('book-detail', args=[pk]))
    else:
        form = ReviewForm()
    
    context = {
        'form': form,
        'book': book,
        'header': 'Add Review',
    }
    
    return render(request, 'catalog/review_form.html', context)

# Author CRUD views
class AuthorCreate(PermissionRequiredMixin, CreateView):
    model = Author
    fields = ['name', 'date_of_birth', 'date_of_death', 'bio']
    initial = {'date_of_death': '11/06/2020'}
    permission_required = 'catalog.add_author'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Create Author'
        return context

class AuthorUpdate(PermissionRequiredMixin, UpdateView):
    model = Author
    fields = ['name', 'date_of_birth', 'date_of_death', 'bio']
    permission_required = 'catalog.change_author'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Update Author'
        return context

class AuthorDelete(PermissionRequiredMixin, DeleteView):
    model = Author
    success_url = reverse_lazy('authors')
    permission_required = 'catalog.delete_author'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Delete Author'
        return context

# Book CRUD views
class BookCreate(PermissionRequiredMixin, CreateView):
    model = Book
    fields = ['title', 'author', 'summary', 'isbn', 'genre', 'language']
    permission_required = 'catalog.add_book'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Create Book'
        return context

class BookUpdate(PermissionRequiredMixin, UpdateView):
    model = Book
    fields = ['title', 'author', 'summary', 'isbn', 'genre', 'language']
    permission_required = 'catalog.change_book'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Update Book'
        return context

class BookDelete(PermissionRequiredMixin, DeleteView):
    model = Book
    success_url = reverse_lazy('books')
    permission_required = 'catalog.delete_book'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Delete Book'
        return context

class GenreDetailView(generic.DetailView):
    """Generic class-based detail view for a genre."""
    model = Genre

class GenreListView(generic.ListView):
    """Generic class-based list view for a list of genres."""
    model = Genre
    paginate_by = 10

class LanguageDetailView(generic.DetailView):
    """Generic class-based detail view for a genre."""
    model = Language

class LanguageListView(generic.ListView):
    """Generic class-based list view for a list of genres."""
    model = Language
    paginate_by = 10

class BookInstanceListView(generic.ListView):
    """Generic class-based view for a list of books."""
    model = BookInstance
    paginate_by = 10

class BookInstanceDetailView(generic.DetailView):
    """Generic class-based detail view for a book."""
    model = BookInstance

class MyBorrowedBooksView(LoginRequiredMixin, generic.ListView):
    """Generic class-based view listing books on loan to current user."""
    model = BookInstance
    template_name = 'catalog/my_borrowed.html'
    paginate_by = 10

    def get_queryset(self):
        return (
            BookInstance.objects.filter(borrower=self.request.user)
            .filter(status__exact='o')
            .order_by('due_back')
        )

@login_required
def logout_view(request):
    logout(request)
    return redirect('index')

class GenreCreate(PermissionRequiredMixin, CreateView):
    model = Genre
    fields = ['name']
    permission_required = 'catalog.add_genre'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Create Genre'
        return context

class GenreUpdate(PermissionRequiredMixin, UpdateView):
    model = Genre
    fields = ['name']
    permission_required = 'catalog.change_genre'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Update Genre'
        return context

class GenreDelete(PermissionRequiredMixin, DeleteView):
    model = Genre
    success_url = reverse_lazy('genres')
    permission_required = 'catalog.delete_genre'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Delete Genre'
        return context

class LanguageCreate(PermissionRequiredMixin, CreateView):
    model = Language
    fields = ['name']
    permission_required = 'catalog.add_language'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Create Language'
        return context

class LanguageUpdate(PermissionRequiredMixin, UpdateView):
    model = Language
    fields = ['name']
    permission_required = 'catalog.change_language'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Update Language'
        return context

class LanguageDelete(PermissionRequiredMixin, DeleteView):
    model = Language
    success_url = reverse_lazy('languages')
    permission_required = 'catalog.delete_language'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Delete Language'
        return context

class BookInstanceCreate(PermissionRequiredMixin, CreateView):
    model = BookInstance
    fields = ['book', 'imprint', 'due_back', 'borrower', 'status']
    permission_required = 'catalog.add_bookinstance'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Create Book Instance'
        return context

class BookInstanceUpdate(PermissionRequiredMixin, UpdateView):
    model = BookInstance
    fields = ['imprint', 'due_back', 'borrower', 'status']
    permission_required = 'catalog.change_bookinstance'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Update Book Instance'
        return context

class BookInstanceDelete(PermissionRequiredMixin, DeleteView):
    model = BookInstance
    success_url = reverse_lazy('bookinstances')
    permission_required = 'catalog.delete_bookinstance'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['header'] = 'Delete Book Instance'
        return context

def ai_chat(request):
    return render(request, 'catalog/ai_chat.html')

@require_POST
@login_required
def like_book(request, pk):
    book = Book.objects.get(pk=pk)
    like, created = BookLike.objects.get_or_create(user=request.user, book=book)
    if not created:
        # 已点赞则取消点赞
        like.delete()
        liked = False
    else:
        liked = True
    like_count = BookLike.objects.filter(book=book).count()
    return JsonResponse({'liked': liked, 'like_count': like_count})

@require_POST
@login_required
def favorite_book(request, pk):
    book = Book.objects.get(pk=pk)
    fav, created = BookFavorite.objects.get_or_create(user=request.user, book=book)
    if not created:
        fav.delete()
        favorited = False
    else:
        favorited = True
    fav_count = BookFavorite.objects.filter(book=book).count()
    return JsonResponse({'favorited': favorited, 'fav_count': fav_count})

class UserCenterView(LoginRequiredMixin, View):
    def get(self, request):
        user = request.user
        borrowed = BookInstance.objects.filter(borrower=user).order_by('-due_back')
        favorites = BookFavorite.objects.filter(user=user).select_related('book')
        likes = BookLike.objects.filter(user=user).select_related('book')
        reviews = Review.objects.filter(user=user).select_related('book')
        context = {
            'user': user,
            'borrowed': borrowed,
            'favorites': favorites,
            'likes': likes,
            'reviews': reviews,
            'header': 'My Profile',
        }
        return render(request, 'catalog/user_center.html', context)

@login_required
def borrow_book_instance(request, pk):
    instance = get_object_or_404(BookInstance, pk=pk, status='a')
    if request.method == 'POST':
        instance.borrower = request.user
        instance.status = 'o'
        instance.due_back = timezone.now().date() + datetime.timedelta(weeks=3)
        instance.save()
        return HttpResponseRedirect(instance.book.get_absolute_url())
    return render(request, 'catalog/borrow_confirm.html', {'instance': instance})

@csrf_exempt
@login_required
def deepseek_chat_view(request):
    if request.method == 'POST':
        import json
        data = json.loads(request.body)
        user_message = data.get('message', '')
        messages = [
            {"role": "system", "content": "你是图书馆AI助手，可以和用户就图书、作者、阅读等话题对话。"},
            {"role": "user", "content": user_message}
        ]
        try:
            ai_reply = deepseek_chat(messages)
        except Exception as e:
            ai_reply = f"AI服务暂时不可用：{e}"
        return JsonResponse({"reply": ai_reply})
    return JsonResponse({"reply": "请用POST方式提交问题。"})
